#include <iostream>
#include <fstream>
#include <cstddef>
//#include <cmath>
//#include <allegro5/allegro.h>
//#include <allegro5/allegro_primitives.h>
#include <string>
#include <cstdlib>
#include <sstream>
#include <limits>
#include <vector>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include "ServerSocket.h"
#include "SocketException.h"

using namespace std;

int kbhit(void)
{
  struct termios oldt, newt;
  int ch;
  int oldf;

  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~(ICANON | ECHO);
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

  ch = getchar();

  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  fcntl(STDIN_FILENO, F_SETFL, oldf);

  if(ch != EOF)
  {
    ungetc(ch, stdin);
    return 1;
  }

  return 0;
}

vector<string> tokenize(const string& str)
{
	vector<string> res;
	stringstream ss(str);
	string s;

	while (getline(ss, s, ' '))
	{
	 res.push_back(s);
	}
	return res;
}

const int totalMoves=10;
const int rN = 2;
const int m=10, n=10, fieldSize=15;
int main()
{
	struct Robot
	{
		int x,y;
	};
	Robot robot[rN];

    string input;
    try{

        //=====LOG===========
        ofstream log;
        string filename="";
        cout<<"Podaj nazwe pliku do logowania (bez rozszerzenia): ";
        cin>>filename;
//        filename.append(".txt");
        log.open(filename.c_str());
        //===================

        ServerSocket server (30000);
        ServerSocket robotSockets[rN];
        int robotsConnected=0;



        while(robotsConnected<rN)
        {

            server.accept(robotSockets[robotsConnected]);
            ServerSocket& newSocket=robotSockets[robotsConnected];
            cout<<"Nowe polaczenie. Wprowadz dowolny znak, aby kontynuowac."<<"\n";
            cin>>input;
            newSocket << "go";
            cout<<"Wprowadz pozycje x robota: ";
            int x,y;
            int dir;
            cin>>x;
            cout<<"Wprowadz pozycje y robota: ";
            cin>>y;
            cout<<"Wprowadz kierunek robota (0/90/180/270): ";
            cin>>dir;
            stringstream ss,ss2;
            ss<<"set_pos " << x <<' '<< y;
            newSocket<<ss.str();
            ss2<<"set_dir "<<dir;
            newSocket << ss2.str();

            robot[robotsConnected].x=x;
			robot[robotsConnected].y=y;
            robotsConnected++;

        }

        int moves=0;

        enum FieldType
        {
        	FT_EMPTY,
        	FT_WALL
        };

        bool pause=false;

        vector<vector<int> > map(m,vector<int>(n,FT_EMPTY));
        vector<string> comToSend[rN];
        vector<vector<double> > occ[rN];
        vector<vector<double> > att[rN];

        for(int i=0;i<rN;i++)
        {
        	occ[i].resize(m,vector<double>(n,0));
        	att[i].resize(m,vector<double>(n,0));
        }

        while(moves<totalMoves)
        {
//            log << moves+1;
            for(int i=0;i<rN;i++)
            {
            	if(!kbhit())
            	{
            		pause=true;
            	}
            	if(moves==5 || moves==9)
            	{
            		comToSend[i].push_back("request_att");
            		comToSend[i].push_back("request_occ");
            	}
//            	char c;
            	cout<<"ruch "<<moves<<", robot "<<i<<endl;//<<": nacisnij przycisk\n";
//            	cin>>c;
            	if(pause)
            	{
            		string k="";
            		while(k!="resume")
            		{
            			cin>>k;
//            			if( k=="fight")
//						{
//						}
//						else
            			if(k=="set_pos")
						{
            				int x,y;
            				cout<<"Podaj x: ";
            				cin>>x;
            				cout<<"Podaj y: ";
            				cin>>y;
            				stringstream ss;
            				ss<<k<<" "<<x<<" "<<y;
            				comToSend[i].push_back(ss.str());
						}
						else if(k=="set_dir")
						{
							char dir;
							cout<<"Podaj kierunek (N/E/S/W): ";
							cin>>dir;
							stringstream ss;
							ss<<k<<" "<<dir;
							comToSend[i].push_back(ss.str());
						}
						else if(k=="request_occ")
						{
							comToSend[i].push_back(k);
						}
						else if(k=="request_att")
						{
							comToSend[i].push_back(k);
						}
						else if(k=="load_occ")
						{
							comToSend[i].push_back(k);
						}
						else if(k=="load_att")
						{
							comToSend[i].push_back(k);
						}
						else if(k=="print")
						{
//							for(int i=0;i<m;i++)
//							{
//								for(int j=0;j<n;j++)
//								{
//									cout<<
//								}
//							}
						}
            		}
            		pause=false;
            	}

            	ServerSocket& rs = robotSockets[i];
            	int nComm=comToSend[i].size();
            	for(int j=0;j<nComm;j++)
            	{
            		string cmd = comToSend[i][0];
            		if(cmd=="load_occ")
            		{

            		}
            		else if(cmd=="load_occ")
					{

					}
            		else if(cmd=="request_occ")
					{
            			rs<<cmd;
						string val="";
						log<<"OCC, robot: "<<i<<", krok: "<<moves<<endl<<endl;
						for(int y=0;y<n;y++)
						{
							for(int x=0;x<m;x++)
							{
								rs>>val;
								stringstream ss;
								ss<<val;
								double dval;
								ss>>dval;
								occ[i][y][x]=dval;
								log<<dval<<" ";
							}
							log<<endl;
						}
						log<<endl;
					}
            		else if(cmd=="request_att")
					{
            			rs<<cmd;
            			string val="";
            			log<<"ATT, robot: "<<i<<", krok: "<<moves<<endl<<endl;
            			for(int y=0;y<n;y++)
            			{
            				for(int x=0;x<m;x++)
            				{
            					rs>>val;
            					stringstream ss;
            					ss<<val;
            					double dval;
            					ss>>dval;
            					att[i][y][x]=dval;
            					log<<dval<<" ";
            				}
            				log<<endl;
            			}
            			log<<endl;
					}
            		else{
            			rs<<cmd;
            		}
            		comToSend[i].erase(comToSend[i].begin());
            	}

                //NEXT TURN

                rs << "next_turn";

                string robCom;
                bool end=false;
                while(!end)
                {
                    rs >> robCom;
                    vector<string> args=tokenize(robCom);
                    if(args[0]=="request")
                    {
                    	int x=atoi(args[1].c_str()),y=atoi(args[2].c_str());
                    	if(robot[1-i].x==x && robot[1-i].y==y)
                    	{
                    		comToSend[1-i].push_back("fight");
                    		rs<<"robot";
                    	}
                    	else if(map[y][x]==FT_WALL)
                    	{
                    		rs<<"wall";
                    	}
                    	else
                    	{
                    		rs<<"empty";
                    	}
                    }
                    else if(args[0]=="end_turn")
                    {
                    	int x=atoi(args[1].c_str()),y=atoi(args[2].c_str());
                    	robot[i].x=x;
                    	robot[i].y=y;
                    	end=true;
                    }
                    else if(args[0]=="nest")
					{
						cout<<"Nest.";
						string s="";
						while(s!="set")
						{
							cin>>s;
						}
					}
                    else
                    {
                    	cout<<"Uwaga! Nieprzewidziana wartosc od robota:"<<robCom<<endl;
                    }
                }

            }
            moves++;
//            log<<endl;
        }
        robotSockets[0]<<"stop";
        robotSockets[1]<<"stop";
        log<<"end";
        log.close();
    }
    catch(SocketException& e)
    {
        cout<<"Blad polaczenia. Tresc bledu: "<<e.description()<<"\nZamykanie programu...";
    }

    cin>>input;
//    delete map;
//    delete[] robots;
//    al_shutdown_primitives_addon();
//    al_destroy_display(display);
//
    return 0;
}

//#include <cmath>
//#include "ViewPort.cpp"
//#include "Client.cpp"
//
//using namespace std;
//
//int main()
//{
//    al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW);
//    ALLEGRO_DISPLAY display = al_create_display(1000, 1000);
//    int displayWidth = al_get_display_width(display);
//    int displayHeight = al_get_display_height(display);
//
//    const int clientsCount =2;//, viewPortsCount = clientsCount+1, viewPortMargin=10;
//    int viewPortWidth =
//        (int)((displayWidth - (viewPortsCount+1)*viewPortMargin)/viewPortsCount);
//
//    ViewPort vp[viewPortsCount];
//    for(int i=0;i<viewPortsCount;i++)
//    {
//        vp[i].setPositionAndScale((i+1)*viewPortMargin+i*viewPortWidth,viewPortMargin,
//                       (i+1)*viewPortMargin+(i+1)*viewPortWidth,viewPortWidth+viewPortMargin);
//    }
//
//    Client clients[clientsCount];
//    for(int i=0;i<clientsCount;i++)
//    {
//        vp[0].addClient(&clients[i]);
//        vp[i+1].addClient(&clients[i]);
//    }
//
//
//    return 0;
//}
